﻿#region Using Directives

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;

#endregion Using Directives


namespace Edinger.Controls
{
    internal sealed class TextEditor : Control
    {
        #region Fields

        private TextEditorDocument document;
        private HScrollBar horizScrollBar;
        private VScrollBar vertScrollBar;

        #endregion Fields


        #region Methods

        private void horizScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            Invalidate();
        }


        protected override void OnLayout(LayoutEventArgs levent)
        {
            vertScrollBar.Bounds = new Rectangle(
                ClientRectangle.Right - SystemInformation.VerticalScrollBarWidth,
                ClientRectangle.Top,
                SystemInformation.VerticalScrollBarWidth,
                ClientRectangle.Height - SystemInformation.HorizontalScrollBarHeight);

            horizScrollBar.Bounds = new Rectangle(
                ClientRectangle.Left,
                ClientRectangle.Bottom - SystemInformation.HorizontalScrollBarHeight,
                ClientRectangle.Width - SystemInformation.VerticalScrollBarWidth,
                SystemInformation.HorizontalScrollBarHeight);

            base.OnLayout(levent);
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            Rectangle gripRectangle = new Rectangle(horizScrollBar.Right, vertScrollBar.Bottom, vertScrollBar.Width, horizScrollBar.Height);
            e.Graphics.FillRectangle(SystemBrushes.Control, gripRectangle);

            if(document == null)
                return;

            int lineHeight = Font.Height;
            int charWidth = TextRenderer.MeasureText("M", Font, Size.Empty, TextFormatFlags.NoPadding).Width;

            if (lineHeight * vertScrollBar.Maximum > DisplayRectangle.Height)
            {
                vertScrollBar.Enabled = true;
                vertScrollBar.LargeChange = (DisplayRectangle.Height / lineHeight) + 1;
            }
            else
            {
                vertScrollBar.Value = 0;
                vertScrollBar.Enabled = false;
                vertScrollBar.Maximum = 1;
            }

            Rectangle lineRect = new Rectangle(-horizScrollBar.Value, 0, DisplayRectangle.Width + horizScrollBar.Value, lineHeight);
            for (int i = vertScrollBar.Value; i < document.LineCount; i++)
            {
                if (lineRect.Top > DisplayRectangle.Bottom)
                    break;

                string s = document.GetLine(i);
                TextRenderer.DrawText(e.Graphics, s, Font, lineRect, ForeColor, BackColor, TextFormatFlags.Left);

                int lineWidth = TextRenderer.MeasureText(s, Font, Size.Empty, TextFormatFlags.Left).Width;
                if (lineWidth > DisplayRectangle.Width)
                {
                    horizScrollBar.Enabled = true;
                    if (horizScrollBar.Maximum < lineWidth)
                        horizScrollBar.Maximum = lineWidth;

                    int largeChange = DisplayRectangle.Width + 1;
                    if (horizScrollBar.LargeChange < largeChange)
                        horizScrollBar.LargeChange = largeChange;
                }
                //else
                //{
                //    horizScrollBar.Value = 0;
                //    horizScrollBar.Enabled = false;
                //    horizScrollBar.Maximum = 1;
                //}

                lineRect.Y += lineHeight;
            }

            base.OnPaint(e);
        }


        private void vertScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            Invalidate();
        }

        #endregion Methods


        #region Properties

        [DefaultValue(typeof(Color), "Window")]
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
            }
        }


        public override Rectangle DisplayRectangle
        {
            get
            {
                Rectangle displayRectangle = ClientRectangle;
                displayRectangle.Width -= vertScrollBar.Width;
                displayRectangle.Height -= horizScrollBar.Height;

                return displayRectangle;
            }
        }


        [Browsable(false)]
        [DefaultValue(null)]
        public TextEditorDocument Document
        {
            get
            {
                return document;
            }
            set
            {
                this.document = value;
                if(document != null)
                {
                    vertScrollBar.Enabled = false;
                    vertScrollBar.Value = 0;
                    vertScrollBar.Maximum = this.document.LineCount;

                    horizScrollBar.Enabled = false;
                    horizScrollBar.Value = 0;
                    horizScrollBar.Maximum = 1;
                }
                Invalidate();
            }
        }


        [DefaultValue(typeof(Color), "WindowText")]
        public override Color ForeColor
        {
            get
            {
                return base.ForeColor;
            }
            set
            {
                base.ForeColor = value;
            }
        }

        #endregion Properties


        #region Constructors

        public TextEditor()
        {
            ResizeRedraw = true;
            DoubleBuffered = true;

            base.BackColor = SystemColors.Window;
            base.ForeColor = SystemColors.WindowText;

            this.vertScrollBar = new VScrollBar();
            this.vertScrollBar.Enabled = false;
            // this.vertScrollBar.Visible = false;
            this.vertScrollBar.Scroll += new ScrollEventHandler(vertScrollBar_Scroll);

            this.horizScrollBar = new HScrollBar();
            this.horizScrollBar.Enabled = false;
            // this.horizScrollBar.Visible = false;
            this.horizScrollBar.Scroll += new ScrollEventHandler(horizScrollBar_Scroll);

            Controls.Add(vertScrollBar);
            Controls.Add(horizScrollBar);

            PerformLayout();
            Invalidate();
        }

        #endregion Constructors
    }
}
